package com.catchbug.servlet;

import java.io.IOException;

import java.security.PrivateKey;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;

import javax.crypto.Cipher;
import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.PreparedQuery;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.FilterOperator;
import com.google.appengine.api.datastore.Query.SortDirection;
import com.google.appengine.api.users.User;
import com.google.appengine.api.users.UserService;
import com.google.appengine.api.users.UserServiceFactory;
import static com.google.appengine.api.datastore.FetchOptions.Builder.*;

@SuppressWarnings("serial")
public class OldServlet extends HttpServlet {
	
	public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {
		process(req, resp);
	}
	
	public void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
		process(req, resp);
	}
	
	public void process(HttpServletRequest req, HttpServletResponse resp) throws IOException {
		try{
			String servletPath = req.getServletPath();
			if(servletPath.indexOf("save.do") > 0){
				save(req, resp);
			}
			
			if(servletPath.indexOf("list.do") > 0){
				list(req, resp);
			}
			
			if(servletPath.indexOf("saveForm.do") > 0){
				saveForm(req, resp);
			}
		}catch(Exception e){
			e.printStackTrace();
			resp.sendRedirect("/index.jsp");
		}
	}

	private void saveForm(HttpServletRequest req, HttpServletResponse resp) throws Exception {
		RequestDispatcher rd = req.getRequestDispatcher("saveForm.jsp");
		rd.forward(req, resp);
	}

	private void list(HttpServletRequest req, HttpServletResponse resp) throws Exception {
		
		HttpSession session = req.getSession();
		String passwd = null;
		
		if(!"Y".equals(session.getAttribute("isCatchbug"))){
			PrivateKey rsaPrivateKey = (PrivateKey)session.getAttribute("rsaPrivateKey");
			
			session.removeAttribute("rsaPrivateKey");
			
			passwd = decryptRsa(rsaPrivateKey, req.getParameter("passwd"));
		}
		
		if("Y".equals(session.getAttribute("isCatchbug")) || "wkqk1108".equals(passwd)){
			session.setAttribute("isCatchbug", "Y");
			DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
			
			Calendar cal = Calendar.getInstance(Locale.KOREA);
			cal.add(Calendar.DATE, -1);
			
			Query deleteQuery = new Query("IP");
			deleteQuery.addFilter("INSDATE", FilterOperator.LESS_THAN_OR_EQUAL, cal.getTime());
			PreparedQuery deletePre = datastore.prepare(deleteQuery);
			List<Entity> deleteList = deletePre.asList(withLimit(1000));
			
			for(Entity entity : deleteList){
				datastore.delete(entity.getKey());
			}
			
			req.setAttribute("entityList", getList());
			req.setAttribute("entityLogList", getLogList());
			
			RequestDispatcher rd = req.getRequestDispatcher("list.jsp");
			rd.forward(req, resp);
		}else{
			resp.sendRedirect("index.jsp");
		}
	}
	
	private List<Entity> getList(){
		DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
		
		Query q = new Query("IP");
		q.addSort("INSDATE", SortDirection.DESCENDING);
		
		PreparedQuery pq = datastore.prepare(q);
		
		List<Entity> entityList = pq.asList(withLimit(1000));
		
		return entityList;
	}
	
	private List<Entity> getLogList(){
		DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
		
		Query q = new Query("IP_LOG");
		q.addSort("INSDATE", SortDirection.DESCENDING);
		
		PreparedQuery pq = datastore.prepare(q);
		List<Entity> logList = pq.asList(withLimit(1000));
		return logList;
	}

	private void save(HttpServletRequest req, HttpServletResponse resp) throws Exception {
		
		Calendar cal = Calendar.getInstance(Locale.KOREA);
		
		DatastoreService datastore = DatastoreServiceFactory.getDatastoreService();
		
		Entity ip = new Entity("IP");
		ip.setProperty("IP_ADDRESS", req.getParameter("ip"));
		ip.setProperty("INSDATE", cal.getTime());
		ip.setProperty("REQ_ADDRESS", req.getRemoteAddr());
		
		datastore.put(ip);
		
		boolean isExist = false;
		for(Entity logItem : getLogList()){
			if(ip.getProperty("REQ_ADDRESS").equals(logItem.getProperty("REQ_ADDRESS"))){
				isExist = true;
				break;
			}
		}
		
		if(!isExist){
			Entity ipLog = new Entity("IP_LOG");
			ipLog.setProperty("IP_ADDRESS", req.getParameter("ip"));
			ipLog.setProperty("INSDATE", cal.getTime());
			ipLog.setProperty("REQ_ADDRESS", req.getRemoteAddr());
			
			datastore.put(ipLog);
		}
		
		resp.sendRedirect("list.do");
	}
	
	private String decryptRsa(PrivateKey privateKey, String securedValue) throws Exception{

		// System.out.println("will decrypt : " + securedValue);
		Cipher cipher = Cipher.getInstance("RSA");
		byte[] encryptedBytes = hexToByteArray(securedValue);
		cipher.init(2, privateKey);
		byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
		String decryptedValue = new String(decryptedBytes, "utf-8");
		// System.out.println("alter decrypt : " + decryptedValue);
		return decryptedValue;
	}
	
	public static byte[] hexToByteArray(String hex){

		if((hex == null) || (hex.length() % 2 != 0)){
			return new byte[0];
		}

		byte[] bytes = new byte[hex.length() / 2];
		for(int i = 0; i < hex.length(); i += 2){
			byte value = (byte) Integer.parseInt(hex.substring(i, i + 2), 16);
			bytes[(int) java.lang.Math.floor(i / 2)] = value;
		}
		return bytes;
	}
}
